// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Tools.cpp 182 2007-11-08 15:17:32Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Polyhedron/Py_Tools.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

#include <include/Kernels.h>
#include <include/iterator.h>
#include <CGAL/Polyhedron_3.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <list>

using boost::python::object;

//BEGIN functions of Vertex Class ========================================
template <class Vertex_handle> 
object point(Vertex_handle& vh)
{
	return object(vh->point());
}

template <class Vertex_handle,class Point> 
void set_point(Vertex_handle& vh,Point p)
{
	vh->point() = p;
}
//==================
template <class Vertex_handle> 
bool is_bivalent(Vertex_handle& vh)
{
	return vh->is_bivalent();
}
//==================
template <class Vertex_handle> 
bool is_trivalent(Vertex_handle& vh)
{
	return vh->is_trivalent();
}

//==================

template <class Vertex_Or_Facet_handle,class Halfedge_handle> 
Halfedge_handle halfedge(Vertex_Or_Facet_handle& h)
{
	return h->halfedge();
}
//==================

template <class Vertex_Or_Facet_handle,class Halfedge_handle> 
void set_halfedge(Vertex_Or_Facet_handle& h,Halfedge_handle he)
{
	return h->set_halfedge(he);
}
//==============

template <class Facet_handle,class Plane_3> 
const Plane_3& plane(Facet_handle& fh)
{
	return fh->plane();
}
//=================

template <class Facet_handle> 
std::size_t facet_degree(Facet_handle& fh)
{
	return fh->facet_degree();
}

//==============
template <class Facet_handle> 
bool is_triangle(Facet_handle& fh)
{
	return fh->is_triangle();
}
//==============
template <class Facet_handle> 
bool is_quad(Facet_handle& fh)
{
	return fh->is_quad();
}

//END of Vertex functions ================================================

//BEGIN================== equivalent to the exporting of '->' operator of Halfedge_handle =====================

template <class Halfedge_handle,class Vertex_handle> 
Vertex_handle vertex(const Halfedge_handle& he)
{
	return he->vertex();
}
//===========================

template <class Halfedge_handle,class Facet_handle> 
Facet_handle facet(const Halfedge_handle& he)
{
	return he->facet();
}
//===========================

template <class Halfedge_handle> 
std::size_t vertex_degree(Halfedge_handle& he)
{
	return he->vertex_degree();
}
//==============

template <class Halfedge_handle> 
bool is_border(Halfedge_handle& he)
{
	return he->is_border();
}

//==============
template <class Halfedge_handle> 
bool is_border_edge(Halfedge_handle& he)
{
	return he->is_border_edge();
}

//==============
template <class Halfedge_handle> 
Halfedge_handle opposite(Halfedge_handle& he)
{
	return he->opposite();
}


template <class Halfedge_handle> 
Halfedge_handle next(Halfedge_handle& he)
{
	return he->next();
}

//==============
template <class Halfedge_handle> 
Halfedge_handle prev(Halfedge_handle& he)
{
	return he->prev();
}

//==============
template <class Halfedge_handle> 
Halfedge_handle next_on_vertex(Halfedge_handle& he)
{
	return he->next_on_vertex();
}
//==============

template <class Halfedge_handle> 
Halfedge_handle prev_on_vertex(Halfedge_handle& he)
{
	return he->prev_on_vertex();
}
//==============
//END================== equivalent to the exporting of '->' operator of Halfedge_handle =====================

//=======================================
//exporting tools of Triangulations.========================
template <class kernel > 
void Py_Tools_Polyhedron()
{
	using namespace boost::python;
	typedef CGAL::Polyhedron_3<kernel> 				Polyhedron_3;
 	typedef typename Polyhedron_3::Halfedge_handle 	Halfedge_handle;
	typedef typename Polyhedron_3::Vertex_handle 	Vertex_handle;
	typedef typename Polyhedron_3::Vertex_iterator 	Vertex_iterator;
	typedef typename Polyhedron_3::Facet_handle 	Facet_iterator;
	typedef typename Polyhedron_3::Facet_handle 	Facet_handle;
	typedef typename Polyhedron_3::Point_iterator 	Point_iterator;
	typedef typename Polyhedron_3::Edge_iterator 	Edge_iterator;
	typedef typename Polyhedron_3::Plane_iterator 	Plane_iterator;
	typedef typename kernel::Plane_3				Plane_3;
	typedef typename kernel::Point_3				Point_3;

const char* Vertex_doc[] ={"\
A vertex optionally stores a point and a reference to an incident halfedge\n\
that points to the vertex.\n\
For mor details see a C++ doc:\n\
http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Polyhedron_ref/Class_Polyhedron_3-Traits---Vertex.html",
"v.point( self ) -> Point_3\nGets a point stored in the vertex v",
"v.halfedge( self) -> halfedge\nan incident halfedge that points to v.",
"v.set_halfedge( self , halfedge h) -> void\nsets incident halfedge to h.\nPrecondition: h is incident, i.e., h.vertex() == v.",
"v.is_bivalent( self ) -> bool\nreturns true if the vertex has exactly two incident edges.",
"v.is_trivalent( self ) -> bool\nreturns true if the vertex has exactly three incident edges.",
"v.vertex_degree( self ) -> int\nthe degree of the vertex, i.e., number of edges emanating from this vertex."
};
	class_<Vertex_handle>("Vertex",Vertex_doc[0],init<Vertex_handle&>())
		.def(self==self)
		.def(self!=self)
		.def("point",&point<Vertex_handle>,Vertex_doc[1])
		.def("set_point",&set_point<Vertex_handle,Point_3>,"v.set_point( self, Point_3 p) -> Sets the point p for the vertex v")
		.def("halfedge",&halfedge<Vertex_handle,Halfedge_handle>,Vertex_doc[2])
		.def("set_halfedge",&set_halfedge<Vertex_handle,Halfedge_handle>,Vertex_doc[3])
		.def("is_bivalent",&is_bivalent<Vertex_handle>,Vertex_doc[4])
		.def("is_trivalent",&is_trivalent<Vertex_handle>,Vertex_doc[5])
		.def("vertex_degree",&vertex_degree<Vertex_handle>,Vertex_doc[6])
	;

const char* Facet_doc[] ={
"For a complete documentation see cgal user manual at:\n http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Polyhedron_ref/Class_Polyhedron_3-Traits---Facet.html",
"	f.plane( self ) -> Plane_3\nplane equation..",
"	f.halfedge( self ) -> Halfedge\nan incident halfedge that points to f.",
"	f.set_halfedge( self , Halfedge h) -> void\nsets incident halfedge to h.\nPrecondition: h is incident, i.e., h.facet() == f.",
"	h.facet_degree( self ) -> int\nthe degree of the facet, i.e., number of edges on the boundary of this facet.",
"	h.is_triangle( self ) -> bool\nreturns true if the facet is a triangle.",
"	h.is_quad( self ) -> bool\nreturns true if the facet is a quadrilateral."

};
	class_<Facet_handle>("Facet",Facet_doc[0],init<Facet_handle&>())
		.def(self==self)
		.def(self!=self)
		.def("plane",&plane<Facet_handle,Plane_3>,return_value_policy< copy_const_reference >(),Facet_doc[1])
		.def("halfedge",&halfedge<Facet_handle,Halfedge_handle>,Facet_doc[2])
		.def("set_halfedge",&set_halfedge<Facet_handle,Halfedge_handle>,Facet_doc[3])
		.def("facet_degree",&facet_degree<Facet_handle>,Facet_doc[4])
		.def("is_triangle",&is_triangle<Facet_handle>,Facet_doc[5])
		.def("is_quad",&is_quad<Facet_handle>,Facet_doc[6])

	;

const char* Halfedge_doc[] ={
"For a complete documentation see cgal user manual at:\n http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Polyhedron_ref/Class_Polyhedron_3-Traits---Halfedge.html",
"	h.opposite( self ) -> Halfedge\nthe opposite halfedge.",
"	h.next( self ) -> Halfedge\nthe next halfedge around the facet.",
"	h.prev( self ) -> Halfedge\nthe previous halfedge around the facet.",
"	h.next_on_vertex( self ) -> Halfedge\nthe next halfedge around the vertex (clockwise).\nIs equal to h.next().opposite().",
"	h.prev_on_vertex( self ) -> Halfedge\nthe previous halfedge around the vertex (counterclockwise).\nIs equal to h.opposite().prev().",
"	h.is_border( self ) -> bool\nis true if h is a border halfedge.",
"	h.is_border_edge( self ) -> bool\nis true if h or h.opposite() is a border halfedge.",
"	h.vertex_degree( self ) -> int\nthe degree of the incident vertex, i.e., number of edges emanating from this vertex.",
"	h.is_bivalent( self ) -> bool\nreturns true if the incident vertex has exactly two incident edges.",
"	h.is_trivalent( self ) -> bool\nreturns true if the incident vertex has exactly three incident edges.",
"	h.facet_degree( self ) -> int\nthe degree of the incident facet, i.e., number of edges on the boundary of this facet.",
"	h.is_triangle( self ) -> bool\nreturns true if the incident facet is a triangle.",
"	h.is_quad( self ) -> bool\nreturns true if the incident facet is a quadrilateral.",
"	h.vertex( self ) -> Vertex\nthe incident vertex of h.",
"	h.facet( self ) ->  facet\nthe incident facet of h. If h is a border halfedge the result is default construction of the handle."

};

	class_<Halfedge_handle>("Halfedge",Halfedge_doc[0],init<Halfedge_handle&>())
		.def("opposite",&opposite<Halfedge_handle>,Halfedge_doc[1])
 		.def("next",&next<Halfedge_handle>,Halfedge_doc[2])
 		.def("prev",&prev<Halfedge_handle>,Halfedge_doc[3])
 		.def("next_on_vertex",&next_on_vertex<Halfedge_handle>,Halfedge_doc[4])
 		.def("prev_on_vertex",&next_on_vertex<Halfedge_handle>,Halfedge_doc[5])
 		.def("is_border",&is_border<Halfedge_handle>,Halfedge_doc[6])
  		.def("is_border_edge",&is_border_edge<Halfedge_handle>,Halfedge_doc[7])
		.def("vertex_degree",&vertex_degree<Halfedge_handle>,Halfedge_doc[8])
 		.def("is_bivalent",&is_bivalent<Halfedge_handle>,Halfedge_doc[9])
 		.def("is_trivalent",&is_trivalent<Halfedge_handle>,Halfedge_doc[10])
 		.def("facet_degree",&facet_degree<Halfedge_handle>,Halfedge_doc[11])
 		.def("is_triangle",&is_triangle<Halfedge_handle>,Halfedge_doc[12])
 		.def("is_quad",&is_quad<Halfedge_handle>,Halfedge_doc[13])
 		.def("vertex",&vertex<Halfedge_handle,Vertex_handle>,Halfedge_doc[14])
 		.def("facet",&facet<Halfedge_handle,Facet_handle>,Halfedge_doc[15])
		.def(self==self)
		.def(self!=self)
	;
//====================================================
}

void export_Tools_Polyhedron()
{
	Py_Tools_Polyhedron<K>();
}
